package com.foreveross.proxyip.local;

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.foreveross.crawl.common.cfg.PropertyUtils;
import com.foreveross.proxyip.ProxyIpModel;
import com.foreveross.proxyip.ProxyipProperties;
import com.foreveross.proxyip.ProxyipProvideException;

/**
 * 简单代理ip池
 * <p>一个带有实例id代理ip池，默认实例ID为DefaultInstance<br/>
 * 一般地，在使用代理ip过程中，若同一个ip针对同一抓取渠道时，会出现渠道阻抗(拒绝访问，出404错误等)，
 * 使用渠道ip池则可以减少这种阻抗<br/>
 * 在使用方(抓取引警)获到实例后，可以从代理ip服务方获取ip存入该池，抓取过程中每请求一次从池中取一个ip对象在client中设置。
 * @author xiangsf
 *
 */
public class ProxyIpSimplePool {
	public Logger logger = LoggerFactory.getLogger(ProxyIpSimplePool.class);
	public final static String DEFAULT_PROXY_POOL_INSTANCEID = "DefaultInstance";
	
	public final static int PROXYIP_POOL_MAXSIZE = 50;
	
	public final static int PROXYIP_DURATIONOFVALIDITY = 3600000;
	
	public final static int PROXYIP_MAX_REPEAT_USECOUNT = 10;
	//池中的代理ip集合
	protected List<ProxyIpModel> proxyIps = null;
	//池中的中转代理IP
	protected List<ProxyIpModel> proxyTempIps = null;
	//池的实例ID
	protected String poolInstanceId = DEFAULT_PROXY_POOL_INSTANCEID;
	//池的最大存储ip数量
	protected int maxSize = PROXYIP_POOL_MAXSIZE;
	//一个IP的可重复使用次数
	protected int maxRepeatCount = PROXYIP_MAX_REPEAT_USECOUNT;
	//池中代理ip失效时长，单位毫秒
	protected int durationOfValidity = PROXYIP_DURATIONOFVALIDITY;
	
	public ProxyIpSimplePool(String poolInstanceId){
			maxSize = PropertyUtils.getIntProperty("proxyip.provider.simplepool.maxsize", 
					ProxyipProperties.CONFIG_FILE, PROXYIP_POOL_MAXSIZE);
			durationOfValidity = PropertyUtils.getIntProperty("proxyip.provider.simplepool.durationOfValidity", 
					ProxyipProperties.CONFIG_FILE, PROXYIP_DURATIONOFVALIDITY);
			maxRepeatCount = PropertyUtils.getIntProperty("proxyip.provider.repeat.use.count", 
					ProxyipProperties.CONFIG_FILE, PROXYIP_DURATIONOFVALIDITY);
			proxyIps = new Vector<ProxyIpModel>(maxSize);
			proxyTempIps = new Vector<ProxyIpModel>(maxSize);
		this.poolInstanceId = poolInstanceId;
	}

	public String getPoolInstanceId() {
		return poolInstanceId;
	}

	public synchronized boolean removeProxyIp(ProxyIpModel model){
		logger.info(String.format("simple pool proxyIps size:%s, proxyTempIps size:%s ", proxyIps.size(), proxyTempIps.size()));
		return proxyTempIps.remove(model);
	}
	/**
	 * 获得可用的IP
	 * @return
	 */
	public synchronized ProxyIpModel getProxyIp(){
		//有则直接获得对象，并称除
		if(proxyIps != null && !proxyIps.isEmpty()){
			//如果超时，则拿下一个
			ProxyIpModel m = proxyIps.remove(0);
			while(m != null && 
					((System.currentTimeMillis()-m.getCreateTime().getTime()) > durationOfValidity || m.getUseCount() >= maxRepeatCount)
					&& !proxyIps.isEmpty()){
				m = proxyIps.remove(0);
			}
			if(logger.isInfoEnabled()){
				logger.info("simple pool size:"+ proxyIps.size());
			}
			if(m != null) proxyTempIps.add(m);
			//累计次数
			m.countUseCount();
			return m;
		}else if(proxyTempIps != null && !proxyTempIps.isEmpty()){
			proxyIps.addAll(proxyTempIps);
			proxyTempIps.clear();
			if(proxyIps.size() < maxSize){ //如果小于数量,则从网上下载
				proxyIps.addAll(this.downloadProxyIp(proxyIps.size()));
			}
			return getProxyIp();
		}else{
			proxyIps.addAll(this.downloadProxyIp(maxSize));
			return getProxyIp();
		}
	}
	
	public int getMaxSize() {
		return maxSize;
	}
	/**
	 * 增加一个代理IP到池中
	 * @param ip
	 */
	public synchronized void addIps(ProxyIpModel ip){
		if(ip != null){
			for(ProxyIpModel m : proxyIps){//过滤重复的
				if(m.getIp().equals(ip.getIp()) && m.getPort()==ip.getPort()){
					return;
				}
			}
			proxyIps.add(ip);
		}
	}
	/**
	 * 增加多个代理IP到池中
	 * @param ip
	 */
	public synchronized void addIps(List<ProxyIpModel> ips){
		if(ips != null && !ips.isEmpty()){
			for(ProxyIpModel model : ips){
				boolean flag = false;
				List<ProxyIpModel> tempList = proxyIps;
				for(ProxyIpModel m : tempList){
					if(model.getIp().equals(m.getIp()) && model.getPort()==m.getPort()){
						flag = true;break;
					}
				}
				tempList = null;
				if(!flag) proxyIps.add(model); //不重复
			}
		}
	}
	
	public synchronized void clear(){
		if(proxyIps != null && !proxyIps.isEmpty()){
			proxyIps.clear();
		}
	}
	
	public synchronized void destory(){
		if(proxyIps != null && !proxyIps.isEmpty()){
			proxyIps.clear();
		}
		proxyIps = null;
	}
	
	private List<ProxyIpModel> downloadProxyIp(int downloadNum){
		List<ProxyIpModel> results = new ArrayList<ProxyIpModel>();
		List<String> ips = null;
		long stime = System.currentTimeMillis();
		ProxyIpModel model = null;
		try{
			ips = HttpDownProxyIp.getInstance().downloadIps(downloadNum);

			if(ips != null && !ips.isEmpty()){
				for(String ip : ips){
					model = new ProxyIpModel(ip.split(":")[0],Integer.valueOf(ip.split(":")[1]));
					model.setLocation(ProxyIpModel.IP_LOCATION_SPOOL);
					results.add(model);
				}
			}
		}catch(Exception e){
			e.printStackTrace();
			throw new ProxyipProvideException(e);
		}finally{
			ips = null;
			model = null;
			if(logger.isInfoEnabled()){
				logger.info(String.format("%s,耗时=%sms", (results.isEmpty() ? "没有获取到代理ip" : "获取到代理ip数量:"+results.size()),  System.currentTimeMillis()-stime));
			}
		}
		return results;
	}
}
